package com.alibaba.middleware.hsf.guide.server.service;

import com.alibaba.middleware.hsf.guide.api.model.OrderModel;
import com.alibaba.middleware.hsf.guide.api.service.OrderService;
import com.alibaba.middleware.hsf.guide.server.dao.OrderDAO;
import com.taobao.hsf.rpc.provider.async.AsyncContext;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class OrderServiceImpl implements OrderService, DisposableBean {

    /**
     * 后台执行线程池
     */
    private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    @Autowired
    private OrderDAO orderDAO;

    @Override
    public OrderModel queryOrder(Long id) {
        Random random = new Random();
        int processTime = random.nextInt(20);
        try {
            Thread.sleep(processTime);
        } catch (InterruptedException e) {
        }
        OrderModel orderModel = orderDAO.queryOrder(id);
        if (orderModel != null) {
            return orderModel;
        }

        throw new RuntimeException("NotFoundOrderModel");
    }

    @Override
    public List<OrderModel> queryOrderList(final List<Long> idList) {
        // 获取AsyncContext实例，需要通过它在异步处理完成时写响应
        final AsyncContext asyncCtx = AsyncContext.startAsync();

        // 新建一个线程异步处理查询订单服务
        // 注意：如果是基于HSF的callback调用，线程是不需要自建的，只需要把AsyncContext作为构造参数或者其他手段传递给callback
        executorService.execute(new Runnable() {

            @Override
            public void run() {
                // 线程切换标识，HSF帮助恢复EagleEye上下文
                // 注意：请在Runnable.run()的第一行调用该方法，否则EagleEye链路会断掉
                // 执行业务
                // 注意：需要自己catch异常，并通过write方法写回（或写回错误码），如果应用有未catch的异常导致线程退出，那么客户端不会收到任何响应，从而引发客户端大量超时。Exception exception = null;
                try {
                    List<OrderModel> orderModelList = new ArrayList<OrderModel>();
                    for (Long id : idList) {
                        OrderModel orderModel = orderDAO.queryOrder(id);
                        if (orderModel != null) {
                            orderModelList.add(orderModel);
                        }
                    }
                    asyncCtx.write(orderModelList);
                } catch (Exception ex) {
                    // 问题异常也写回去
                    asyncCtx.write(ex);
                }
            }
        });

        // 直接返回null，真正的结果会通过AsyncContext写到客户端
        return null;
    }

    @Override
    public void destroy() throws Exception {
        executorService.shutdown();
    }
}
